﻿(function($) {
  $.formValidator =
  {
    //全局配置
    initConfig: function(controlOptions) {
      var settings = {};
      $.extend(true, settings, initConfig_setting, controlOptions || {});
      //如果是精简模式，发生错误的时候，第一个错误的控件就不获得焦点
      if (settings.mode == "SingleTip") {
        settings.errorFocus = false;
      };
      //如果填写了表单和按钮，就注册验证事件
      if (settings.formID != "") {
        $("#" + settings.formID).submit(function() {
          if (settings.ajaxForm != null) {
            $.formValidator.ajaxForm(settings.validatorGroup, settings.ajaxForm);
            return false;
          } else {
            return $.formValidator.bindSubmit(settings);
          }
        });
      }
      validatorGroup_setting.push(settings);
      //读取主题对应的脚步
      var scriptSrcArray = fv_scriptSrc.split("/");
      var jsName = scriptSrcArray[scriptSrcArray.length - 1];
      var themedir = fv_scriptSrc.replace(jsName, "");
      $.ajax({
        async: false,
        type: "GET",
        url: themedir + "themes/" + settings.theme + "/js/theme.js",
        dataType: "script",
        error: function() { alert("当前皮肤加载出错，请确认皮肤【" + settings.theme + "】是否存在") }
      });
      //读取主题对应的样式
      if ($.browser.msie) {
        var css = document.createElement("link");
        css.rel = "stylesheet";
        css.type = "text/css";
        css.href = themedir + "themes/" + settings.theme + "/style/style.css";
        document.getElementsByTagName("head")[0].appendChild(css);
      } else {
        var style = document.createElement("style");
        style.setAttribute("type", "text/css");
        var styCss = "@import url('" + themedir + "themes/" + settings.theme + "/style/style.css');";
        if (style.styleSheet) {
          style.styleSheet.cssText = styCss;
        } else {
          style.appendChild(document.createTextNode(styCss));
        }
        document.getElementsByTagName("head")[0].appendChild(style);
      }
    },

    //调用验证函数
    bindSubmit: function(settings) {
      if (settings.ajaxCountValid > 0 && settings.ajaxPrompt != "") {
        alert(settings.ajaxPrompt);
        return false;
      }
      return $.formValidator.pageIsValid(settings.validatorGroup);
    },

    //各种校验方式支持的控件类型
    sustainType: function(elem, validateType) {
      var srcTag = elem.tagName;
      var stype = elem.type;
      switch (validateType) {
      case "formValidator":
        return true;
      case "inputValidator":
        return (srcTag == "INPUT" || srcTag == "TEXTAREA" || srcTag == "SELECT");
      case "compareValidator":
        return ((srcTag == "INPUT" || srcTag == "TEXTAREA") ? (stype != "checkbox" && stype != "radio") : false);
      case "ajaxValidator":
        return (stype == "text" || stype == "textarea" || stype == "file" || stype == "password" || stype == "select-one");
      case "regexValidator":
        return ((srcTag == "INPUT" || srcTag == "TEXTAREA") ? (stype != "checkbox" && stype != "radio") : false);
      case "functionValidator":
        return true;
      case "passwordValidator":
        return stype == "password";
      }
    },

    //如果validator对象对应的element对象的validator属性追加要进行的校验。
    appendValid: function(id, setting) {
      //如果是各种校验不支持的类型，就不追加到。返回-1表示没有追加成功
      var elem = $("#" + id).get(0);
      var validateType = setting.validateType;
      if (!$.formValidator.sustainType(elem, validateType)) return -1;
      //重新初始化
      if (validateType == "formValidator" || elem.settings == undefined) {
        elem.settings = new Array();
      }
      var len = elem.settings.push(setting);
      elem.settings[len - 1].index = len - 1;
      return len - 1;
    },

    //获取校验组信息。
    getInitConfig: function(validatorGroup) {
      var config = null;
      $.each(validatorGroup_setting, function(i, n) {
        if (validatorGroup_setting[i].validatorGroup == validatorGroup) {
          config = validatorGroup_setting[i];
          return false;
        }
      });
      return config;
    },

    //设置显示信息
    setTipState: function(elem, showclass, showmsg) {
      var initConfig = $.formValidator.getInitConfig(elem.validatorGroup);
      var tip = $("#" + elem.settings[0].tipID);
      if (showmsg == null || showmsg == "") {
        tip.hide();
      } else {
        if (initConfig.mode == "SingleTip") {
          //显示和保存提示信息
          $("#fv_content").html(showmsg);
          elem.Tooltip = showmsg;
          if (showclass != "onError") {
            tip.hide();
          }
        } else {
          var html = showclass == "onShow" ? onShowHtml : (showclass == "onFocus" ? onFocusHtml : (showclass == "onCorrect" ? onCorrectHtml : onErrorHtml));
          if (html.length = 0 || showmsg == "") {
            tip.hide();
          } else {
            if (elem.validatorPasswordIndex > 0 && showclass == "onCorrect") {
              var setting = elem.settings[elem.validatorPasswordIndex];
              var level = $.formValidator.passwordValid(elem);
              showmsg = "";
              if (level == -1 && setting.onErrorContinueChar != "") {
                showmsg = setting.onErrorContinueChar;
              } else if (level == -2 && setting.onErrorSameChar != "") {
                showmsg = setting.onErrorSameChar;
              } else if (level == -3 && setting.onErrorCompareSame != "") {
                showmsg = setting.onErrorCompareSame;
              }
              if (showmsg != "") {
                $.formValidator.setTipState(elem, "onError", showmsg);
                return;
              }
              showmsg = passwordStrengthText[level <= 0 ? 0 : level - 1];
            }
            html = html.replace(/\$class\$/g, showclass).replace(/\$data\$/g, showmsg);
            tip.html(html).show();
          }
          var stype = elem.type;
          if (stype == "password" || stype == "text" || stype == "file") {
            jqobj = $(elem);
            if (onShowClass != "" && showclass == "onShow") {
              jqobj.removeClass().addClass(onShowClass);
            };
            if (onFocusClass != "" && showclass == "onFocus") {
              jqobj.removeClass().addClass(onFocusClass);
            };
            if (onCorrectClass != "" && showclass == "onCorrect") {
              jqobj.removeClass().addClass(onCorrectClass);
            };
            if (onErrorClass != "" && showclass == "onError") {
              jqobj.removeClass().addClass(onErrorClass);
            };
          }
        }
      }
    },

    //把提示层重置成原始提示(如果有defaultPassed,应该设置为onCorrect)
    resetTipState: function(validatorGroup) {
      if (validatorGroup == undefined) {
        validatorGroup = "1";
      };
      var initConfig = $.formValidator.getInitConfig(validatorGroup);
      $.each(initConfig.validObjects, function() {
        var setting = this.settings[0];
        var passed = setting.defaultPassed;
        $.formValidator.setTipState(this, passed ? "onCorrect" : "onShow", passed ? $.formValidator.getStatusText(this, setting.onCorrect) : setting.onShow);
      });
    },

    //设置错误的显示信息
    setFailState: function(tipID, showmsg) {
      $.formValidator.setTipState($("#" + tipID).get(0), "onError", showmsg);
    },

    //根据单个对象,正确:正确提示,错误:错误提示
    showMessage: function(returnObj) {
      var id = returnObj.id;
      var elem = $("#" + id).get(0);
      var isValid = returnObj.isValid;
      var setting = returnObj.setting; //正确:setting[0],错误:对应的setting[i]
      var showmsg = "", showclass = "";
      var intiConfig = $.formValidator.getInitConfig(elem.validatorGroup);
      if (!isValid) {
        showclass = "onError";
        if (setting.validateType == "ajaxValidator") {
          if (setting.lastValid == "") {
            showclass = "onLoad";
            showmsg = setting.onWait;
          } else {
            showmsg = $.formValidator.getStatusText(elem, setting.onError);
          }
        } else {
          showmsg = (returnObj.errormsg == "" ? $.formValidator.getStatusText(elem, setting.onError) : returnObj.errormsg);

        }
        if (intiConfig.mode == "AlertTip") {
          if (elem.validValueOld != $(elem).val()) {
            alert(showmsg);
          }
        } else {
          $.formValidator.setTipState(elem, showclass, showmsg);
        }
      } else {
        //验证成功后,如果没有设置成功提示信息,则给出默认提示,否则给出自定义提示;允许为空,值为空的提示
        showmsg = $.formValidator.isEmpty(id) ? setting.onEmpty : $.formValidator.getStatusText(elem, setting.onCorrect);
        $.formValidator.setTipState(elem, "onCorrect", showmsg);
      }
      return showmsg;
    },

    showAjaxMessage: function(returnObj) {
      var elem = $("#" + returnObj.id).get(0);
      var setting = elem.settings[returnObj.ajax];
      var validValueOld = elem.validValueOld;
      var validvalue = $(elem).val();
      returnObj.setting = setting;
      //defaultPassed还未处理
      if (validValueOld != validvalue || validValueOld == validvalue && elem.onceValided == undefined) {
        $.formValidator.ajaxValid(returnObj);
      } else {
        if (setting.isValid != undefined && !setting.isValid) {
          elem.lastshowclass = "onError";
          elem.lastshowmsg = $.formValidator.getStatusText(elem, setting.onError);
        }
        $.formValidator.setTipState(elem, elem.lastshowclass, elem.lastshowmsg);
      }
    },

    //获取指定字符串的长度
    getLength: function(id) {
      var srcjo = $("#" + id);
      var elem = srcjo.get(0);
      var sType = elem.type;
      var len = 0;
      switch (sType) {
      case "text":
      case "hidden":
      case "password":
      case "textarea":
      case "file":
        var val = srcjo.val();
        var setting = elem.settings[0];
        //如果有显示提示内容的，要忽略掉
        if (elem.isInputControl && elem.value == setting.onShowText) {
          val = "";
        }
        var initConfig = $.formValidator.getInitConfig(elem.validatorGroup);
        if (initConfig.wideWord) {
          for (var i = 0; i < val.length; i++) {
            len = len + ((val.charCodeAt(i) >= 0x4e00 && val.charCodeAt(i) <= 0x9fa5) ? 2 : 1);
          }
        } else {
          len = val.length;
        }
        break;
      case "checkbox":
      case "radio":
        len = $("input[type='" + sType + "'][name='" + srcjo.attr("name") + "']:checked").length;
        break;
      case "select-one":
        len = elem.options ? elem.options.selectedIndex : -1;
        break;
      case "select-multiple":
        len = $("select[name=" + elem.name + "] option:selected").length;
        break;
      }
      return len;
    },

    //结合empty这个属性，判断仅仅是否为空的校验情况。
    isEmpty: function(id) {
      return ($("#" + id).get(0).settings[0].empty && $.formValidator.getLength(id) == 0);
    },

    //对外调用：判断单个表单元素是否验证通过，不带回调函数
    isOneValid: function(id) {
      return $.formValidator.oneIsValid(id).isValid;
    },

    //验证单个是否验证通过,正确返回settings[0],错误返回对应的settings[i]
    oneIsValid: function(id) {
      var returnObj = new Object();
      var elem = $("#" + id).get(0);
      var initConfig = $.formValidator.getInitConfig(elem.validatorGroup);
      returnObj.initConfig = initConfig;
      returnObj.id = id;
      returnObj.ajax = -1;
      returnObj.errormsg = ""; //自定义错误信息
      var settings = elem.settings;
      var settingslen = settings.length;
      var validateType;
      //只有一个formValidator的时候不检验
      if (settingslen == 1) {
        settings[0].bind = false;
      }
      if (!settings[0].bind) {
        return null;
      }
      $.formValidator.resetInputValue(true, initConfig, id);
      for (var i = 0; i < settingslen; i ++) {
        if (i == 0) {
          //如果为空，直接返回正确
          if ($.formValidator.isEmpty(id)) {
            returnObj.isValid = true;
            returnObj.setting = settings[0];
            break;
          }
          continue;
        }
        returnObj.setting = settings[i];
        validateType = settings[i].validateType;
        //根据类型触发校验
        switch (validateType) {
        case "inputValidator":
          $.formValidator.inputValid(returnObj);
          break;
        case "compareValidator":
          $.formValidator.compareValid(returnObj);
          break;
        case "regexValidator":
          $.formValidator.regexValid(returnObj);
          break;
        case "functionValidator":
          $.formValidator.functionValid(returnObj);
          break;
        case "ajaxValidator":
          //如果是ajax校验，这里直接取上次的结果值
          returnObj.ajax = i;
          break;
        case "passwordValidator":
          break;
        }
        //校验过一次
        elem.onceValided = true;
        if (!settings[i].isValid) {
          returnObj.isValid = false;
          returnObj.setting = settings[i];
          break;
        } else {
          returnObj.isValid = true;
          returnObj.setting = settings[0];
          if (settings[i].validateType == "ajaxValidator") {
            break;
          };
        }
      }
      $.formValidator.resetInputValue(false, initConfig, id);
      return returnObj;
    },

    //验证所有需要验证的对象，并返回是否验证成功（如果曾经触发过ajaxValidator，提交的时候就不触发校验，直接读取结果）
    pageIsValid: function(validatorGroup) {
      if (validatorGroup == undefined) {
        validatorGroup = "1";
      };
      var isValid = true, returnObj, firstErrorMessage = "", errorMessage;
      var error_tip = "^", thefirstid, name, name_list = "^";
      var errorlist = new Array();
      //设置提交状态、ajax是否出错、错误列表
      var initConfig = $.formValidator.getInitConfig(validatorGroup);
      initConfig.status = "sumbiting";
      initConfig.ajaxCountSubmit = 0;
      //遍历所有要校验的控件,如果存在ajaxValidator就先直接触发
      $.each(initConfig.validObjects, function() {
        if ($(this).length == 0) {
          return true;
        };
        if (this.settings[0].bind && this.validatorAjaxIndex != undefined && this.onceValided == undefined) {
          returnObj = $.formValidator.oneIsValid(this.id);
          if (returnObj.ajax == this.validatorAjaxIndex) {
            initConfig.status = "sumbitingWithAjax";
            $.formValidator.ajaxValid(returnObj);
          }
        }
      });
      //如果有提交的时候有触发ajaxValidator，所有的处理都放在ajax里处理
      if (initConfig.ajaxCountSubmit > 0) {
        return false;
      }
      //遍历所有要校验的控件
      $.each(initConfig.validObjects, function() {
        //只校验绑定的控件
        if ($(this).length == 0) {
          return true;
        };
        if (this.settings[0].bind) {
          name = this.name;
          //相同name只校验一次
          if (name_list.indexOf("^" + name + "^") == -1) {
            onceValided = this.onceValided == undefined ? false : this.onceValided;
            if (name) {
              name_list = name_list + name + "^";
            };
            returnObj = $.formValidator.oneIsValid(this.id);
            if (returnObj) {
              //校验失败,获取第一个发生错误的信息和ID
              if (!returnObj.isValid) {
                //记录不含ajaxValidator校验函数的校验结果
                isValid = false;
                errorMessage = returnObj.errormsg == "" ? returnObj.setting.onError : returnObj.errormsg;
                errorlist[errorlist.length] = errorMessage;
                if (thefirstid == null) {
                  thefirstid = returnObj.id;
                };
                if (firstErrorMessage == "") {
                  firstErrorMessage = errorMessage;
                };
              }
              //为了解决使用同个TIP提示问题:后面的成功或失败都不覆盖前面的失败
              if (initConfig.mode != "AlertTip") {
                var tipID = this.settings[0].tipID;
                if (error_tip.indexOf("^" + tipID + "^") == -1) {
                  if (!returnObj.isValid) {
                    error_tip = error_tip + tipID + "^";
                  };
                  $.formValidator.showMessage(returnObj);
                }
              }
            }
          }
        }
      });

      //成功或失败进行回调函数的处理，以及成功后的灰掉提交按钮的功能
      if (isValid) {
        if (!initConfig.onSuccess()) {
          return false;
        };
        if (initConfig.submitOnce) {
          $(":submit, :button, :reset").attr("disabled", true);
        }
      } else {
        initConfig.onError(firstErrorMessage, $("#" + thefirstid).get(0), errorlist);
        if (thefirstid && initConfig.errorFocus) {
          $("#" + thefirstid).focus();
        };
      }
      initConfig.status = "init";
      if (isValid && initConfig.debug) {
        alert("现在正处于调试模式(debug:true)，不能提交");
      }
      return !initConfig.debug && isValid;
    },

    //整个表单
    ajaxForm: function(validatorGroup, option, formid) {
      if (validatorGroup == undefined) {
        validatorGroup = "1";
      };
      var setting = {};
      $.extend(true, setting, ajaxForm_setting, option || {});
      var initConfig = $.formValidator.getInitConfig(validatorGroup);
      if (formid == undefined) {
        formid = initConfig.formID;
        if (formid == "") {
          alert("表单ID未传入");
          return false;
        };
      };
      if (!$.formValidator.pageIsValid(validatorGroup)) {
        return false;
      };
      var ls_url = setting.url;
      var parm = $.formValidator.serialize("#" + formid);
      ls_url = ls_url + (ls_url.indexOf("?") > -1 ? ("&" + parm) : ("?" + parm));
      alert(ls_url);
      $.ajax(
      {
        type: setting.type,
        url: ls_url,
        cache: setting.cache,
        data: setting.data,
        async: setting.async,
        timeout: setting.timeout,
        dataType: setting.dataType,
        beforeSend: function(jqXHR, configs) { //再服务器没有返回数据之前，先回调提交按钮
          if (setting.buttons && setting.buttons.length > 0) {
            setting.buttons.attr({ "disabled": true });
          };
          return setting.beforeSend(jqXHR, configs);
        },
        success: function(data, textStatus, jqXHR) { setting.success(data, textStatus, jqXHR); },
        complete: function(jqXHR, textStatus) {
          if (setting.buttons && setting.buttons.length > 0) {
            setting.buttons.attr({ "disabled": false });
          };
          setting.complete(jqXHR, textStatus);
        },
        error: function(jqXHR, textStatus, errorThrown) { setting.error(jqXHR, textStatus, errorThrown); }
      });
    },

    //把编码decodeURIComponent反转之后，再escape
    serialize: function(objs, initConfig) {
      if (initConfig != undefined) {
        $.formValidator.resetInputValue(true, initConfig);
      };
      var parmString = $(objs).serialize();
      if (initConfig != undefined) {
        $.formValidator.resetInputValue(false, initConfig);
      };
      var parmArray = parmString.split("&");
      var parmStringNew = "";
      $.each(parmArray, function(index, data) {
        var li_pos = data.indexOf("=");
        if (li_pos > 0) {
          var name = data.substring(0, li_pos);
          var value = escape(decodeURIComponent(data.substr(li_pos + 1)));
          var parm = name + "=" + value;
          parmStringNew = parmStringNew == "" ? parm : parmStringNew + "&" + parm;
        }
      });
      return parmStringNew;
    },

    //ajax校验
    ajaxValid: function(returnObj) {
      var id = returnObj.id;
      var srcjo = $("#" + id);
      var elem = srcjo.get(0);
      var initConfig = returnObj.initConfig;
      var settings = elem.settings;
      var setting = settings[returnObj.ajax];
      var ls_url = setting.url;
      //获取要传递的参数
      var validatorGroup = elem.validatorGroup;
      var initConfig = $.formValidator.getInitConfig(validatorGroup);
      var parm = $.formValidator.serialize(initConfig.ajaxObjects);
      //添加触发的控件名、随机数、传递的参数
      parm = "clientid=" + id + "&" + (setting.randNumberName ? setting.randNumberName + "=" + ((new Date().getTime()) + Math.round(Math.random() * 10000)) : "") + (parm.length > 0 ? "&" + parm : "");
      ls_url = ls_url + (ls_url.indexOf("?") > -1 ? ("&" + parm) : ("?" + parm));
      //发送ajax请求
      $.ajax(
      {
        type: setting.type,
        url: ls_url,
        cache: setting.cache,
        data: setting.data,
        async: setting.async,
        timeout: setting.timeout,
        dataType: setting.dataType,
        success: function(data, textStatus, jqXHR) {
          var lb_ret, ls_status, ls_msg, lb_isValid = false;
          $.formValidator.dealAjaxRequestCount(validatorGroup, -1);

          //根据业务判断设置显示信息
          lb_ret = setting.success(data, textStatus, jqXHR);
          if ((typeof lb_ret) == "string") {
            ls_status = "onError";
            ls_msg = lb_ret;
          } else if (lb_ret) {
            lb_isValid = true;
            ls_status = "onCorrect";
            ls_msg = settings[0].onCorrect;
          } else {
            ls_status = "onError";
            ls_msg = $.formValidator.getStatusText(elem, setting.onError);
            alert(ls_msg);
          }
          setting.isValid = lb_isValid;
          $.formValidator.setTipState(elem, ls_status, ls_msg);
          //提交的时候触发了ajax校验，等ajax校验完成，无条件重新校验
          if (returnObj.initConfig.status == "sumbitingWithAjax" && returnObj.initConfig.ajaxCountSubmit == 0) {
            if (initConfig.formID != "") {
              $("#" + initConfig.formID).trigger("submit");
            }
          }
        },
        complete: function(jqXHR, textStatus) {
          if (setting.buttons && setting.buttons.length > 0) {
            setting.buttons.attr({ "disabled": false });
          };
          setting.complete(jqXHR, textStatus);
        },
        beforeSend: function(jqXHR, configs) {
          //本控件如果正在校验，就中断上次
          if (this.lastXMLHttpRequest) {
            this.lastXMLHttpRequest.abort();
          };
          this.lastXMLHttpRequest = jqXHR;
          //再服务器没有返回数据之前，先回调提交按钮
          if (setting.buttons && setting.buttons.length > 0) {
            setting.buttons.attr({ "disabled": true });
          };
          var lb_ret = setting.beforeSend(jqXHR, configs);
          var isValid = false;
          //无论是否成功都当做失败处理
          setting.isValid = false;
          if ((typeof lb_ret) == "boolean" && lb_ret) {
            isValid = true;
            $.formValidator.setTipState(elem, "onLoad", settings[returnObj.ajax].onWait);
          } else {
            isValid = false;
            $.formValidator.setTipState(elem, "onError", lb_ret);
          }
          setting.lastValid = "-1";
          if (isValid) {
            $.formValidator.dealAjaxRequestCount(validatorGroup, 1);
          }
          return isValid;
        },
        error: function(jqXHR, textStatus, errorThrown) {
          $.formValidator.dealAjaxRequestCount(validatorGroup, -1);
          $.formValidator.setTipState(elem, "onError", $.formValidator.getStatusText(elem, setting.onError));
          setting.isValid = false;
          setting.error(jqXHR, textStatus, errorThrown);
        },
        processData: setting.processData
      });
    },

    //处理ajax的请求个数
    dealAjaxRequestCount: function(validatorGroup, val) {
      var initConfig = $.formValidator.getInitConfig(validatorGroup);
      initConfig.ajaxCountValid = initConfig.ajaxCountValid + val;
      if (initConfig.status == "sumbitingWithAjax") {
        initConfig.ajaxCountSubmit = initConfig.ajaxCountSubmit + val;
      }
    },

    //对正则表达式进行校验（目前只针对input和textarea）
    regexValid: function(returnObj) {
      var id = returnObj.id;
      var setting = returnObj.setting;
      var srcTag = $("#" + id).get(0).tagName;
      var elem = $("#" + id).get(0);
      var isValid;
      //如果有输入正则表达式，就进行表达式校验
      if (elem.settings[0].empty && elem.value == "") {
        setting.isValid = true;
      } else {
        var regexArray = setting.regExp;
        setting.isValid = false;
        if ((typeof regexArray) == "string") regexArray = [regexArray];
        $.each(regexArray, function() {
          var r = this;
          if (setting.dataType == "enum") {
            r = eval("regexEnum." + r);
          }
          if (r == undefined || r == "") {
            return false;
          }
          isValid = (new RegExp(r, setting.param)).test($(elem).val());

          if (setting.compareType == "||" && isValid) {
            setting.isValid = true;
            return false;
          }
          if (setting.compareType == "&&" && !isValid) {
            return false;
          }
        });
        if (!setting.isValid) setting.isValid = isValid;
      }
    },

    //函数校验。返回true/false表示校验是否成功;返回字符串表示错误信息，校验失败;如果没有返回值表示处理函数，校验成功
    functionValid: function(returnObj) {
      var id = returnObj.id;
      var setting = returnObj.setting;
      var srcjo = $("#" + id);
      var lb_ret = setting.fun(srcjo.val(), srcjo.get(0));
      if (lb_ret != undefined) {
        if ((typeof lb_ret) === "string") {
          setting.isValid = false;
          returnObj.errormsg = lb_ret;
        } else {
          setting.isValid = lb_ret;
        }
      } else {
        setting.isValid = true;
      }
    },

    //对input和select类型控件进行校验
    inputValid: function(returnObj) {
      var id = returnObj.id;
      var setting = returnObj.setting;
      var srcjo = $("#" + id);
      var elem = srcjo.get(0);
      var val = srcjo.val();
      var sType = elem.type;
      var len = $.formValidator.getLength(id);
      var empty = setting.empty, emptyError = false;
      switch (sType) {
      case "text":
      case "hidden":
      case "password":
      case "textarea":
      case "file":
        if (setting.type == "size") {
          empty = setting.empty;
          if (!empty.leftEmpty) {
            emptyError = (val.replace(/^[ \s]+/, "").length != val.length);
          }
          if (!emptyError && !empty.rightEmpty) {
            emptyError = (val.replace(/[ \s]+$/, "").length != val.length);
          }
          if (emptyError && empty.emptyError) {
            returnObj.errormsg = empty.emptyError;
          }
        }
      case "checkbox":
      case "select-one":
      case "select-multiple":
      case "radio":
        var lb_go_on = false;
        if (sType == "select-one" || sType == "select-multiple") {
          setting.type = "size";
        }
        var type = setting.type;
        if (type == "size") { //获得输入的字符长度，并进行校验
          if (!emptyError) {
            lb_go_on = true;
          }
          if (lb_go_on) {
            val = len;
          }
        } else if (type == "date" || type == "datetime") {
          var isok = false;
          if (type == "date") {
            lb_go_on = isDate(val);
          };
          if (type == "datetime") {
            lb_go_on = isDate(val);
          };
          if (lb_go_on) {
            val = new Date(val);
            setting.min = new Date(setting.min);
            setting.max = new Date(setting.max);
          };
        } else {
          stype = (typeof setting.min);
          if (stype == "number") {
            val = (new Number(val)).valueOf();
            if (!isNaN(val)) {
              lb_go_on = true;
            }
          }
          if (stype == "string") {
            lb_go_on = true;
          }
        }
        setting.isValid = false;
        if (lb_go_on) {
          if (val < setting.min || val > setting.max) {
            if (val < setting.min && setting.onErrorMin) {
              returnObj.errormsg = setting.onErrorMin;
            }
            if (val > setting.min && setting.onErrorMax) {
              returnObj.errormsg = setting.onErrorMax;
            }
          } else {
            setting.isValid = true;
          }
        }
        break;
      }
    },

    //对两个控件进行比较校验
    compareValid: function(returnObj) {
      var id = returnObj.id;
      var setting = returnObj.setting;
      var srcjo = $("#" + id);
      var desjo = $("#" + setting.desID);
      var ls_dataType = setting.dataType;

      curvalue = srcjo.val();
      ls_data = desjo.val();
      if (ls_dataType == "number") {
        if (!isNaN(curvalue) && !isNaN(ls_data)) {
          curvalue = parseFloat(curvalue);
          ls_data = parseFloat(ls_data);
        } else {
          return;
        }
      }
      if (ls_dataType == "date" || ls_dataType == "datetime") {
        var isok = false;
        if (ls_dataType == "date") {
          isok = (isDate(curvalue) && isDate(ls_data));
        };
        if (ls_dataType == "datetime") {
          isok = (isDateTime(curvalue) && isDateTime(ls_data));
        };
        if (isok) {
          curvalue = new Date(curvalue);
          ls_data = new Date(ls_data);
        } else {
          return;
        }
      }

      switch (setting.operateor) {
      case "=":
        setting.isValid = (curvalue == ls_data);
        break;
      case "!=":
        setting.isValid = (curvalue != ls_data);
        break;
      case ">":
        setting.isValid = (curvalue > ls_data);
        break;
      case ">=":
        setting.isValid = (curvalue >= ls_data);
        break;
      case "<":
        setting.isValid = (curvalue < ls_data);
        break;
      case "<=":
        setting.isValid = (curvalue <= ls_data);
        break;
      default:
        setting.isValid = false;
        break;
      }
    },

    //获取密码校验等级
    passwordValid: function(elem) {
      var setting = elem.settings[elem.validatorPasswordIndex];
      var pwd = elem.value;

//是否为连续字符
      function isContinuousChar(str) {
        var str = str.toLowerCase();
        var flag = 0;
        for (var i = 0; i < str.length; i++) {
          if (str.charCodeAt(i) != flag + 1 && flag != 0)
            return false;
          else
            flag = str.charCodeAt(i);
        }
        return true;
      }

//是否字符都相同
      function isSameChar(str) {
        var str = str.toLowerCase();
        var flag = 0;
        for (var i = 0; i < str.length; i++) {
          if (str.charCodeAt(i) != flag && flag != 0)
            return false;
          else
            flag = str.charCodeAt(i);
        }
        return true;
      }

//获取标记所在的位置，用1表示
      function getFlag(val, sum, index) {
        if (sum == undefined) {
          sum = [0, 0, 0, 0];
        }
        if (index == undefined) {
          index = -1;
        };
        index ++;
        sum[index] = val % 2;
        val = Math.floor(val / 2);
        if (val == 1 || val == 0) {
          sum[index + 1] = val;
          return sum;
        }
        sum = getFlag(val, sum, index);
        return sum;
      }

      //判断密码各个位置的组成情况
      if (pwd == "") {
        return 0;
      };
      if (setting.onErrorContinueChar != "" && isContinuousChar(pwd)) {
        return -1;
      };
      if (setting.onErrorSameChar != "" && isSameChar(pwd)) {
        return -2;
      };
      if (setting.compareID != "" && $("#" + setting.compareID).val() == pwd) {
        return -3;
      };
      var sum1 = [0, 0, 0, 0];
      var specicalChars = "!,@,#,$,%,\^,&,*,?,_,~";
      var len = pwd.length;
      for (var i = 0; i < len; i++) {
        var c = pwd.charCodeAt(i);
        if (c >= 48 && c <= 57) { //数字
          sum1[0] += 1;
        } else if (c >= 97 && c <= 122) { //小写字母
          sum1[1] += 1;
        } else if (c >= 65 && c <= 90) { //大写字母
          sum1[2] += 1;
        } else if (specicalChars.indexOf(pwd.substr(i, 1)) >= 0) { //特殊字符
          sum1[3] += 1;
        }
      }

      //遍历json变量获取字符串
      var returnLevel = 0;
      var hasFind = true;
      $.each(passwordStrengthRule, function(j, n) {
        var level = n.level;
        var rules = n.rule;
        $.each(rules, function(i, rule) {
          var index = 0;
          //依次编译所有的、有配置(该位置==1)的节点
          hasFind = true;
          $.each(getFlag(rule.flag), function(k, value) {
            if (value == 1) {
              val = rule.value[index++];
              var val = val == 0 ? len : (val > len ? len : val);
              if (sum1[k] < val) {
                hasFind = false;
                return false;
              }
            }
          });
          if (hasFind) {
            returnLevel = level;
            return false;
          }
        });
        if (hasFind) {
          returnLevel = level;
        }
      });
      return returnLevel;
    },

    //定位漂浮层
    localTooltip: function(e) {
      e = e || window.event;
      var mouseX = e.pageX || (e.clientX ? e.clientX + document.body.scrollLeft : 0);
      var mouseY = e.pageY || (e.clientY ? e.clientY + document.body.scrollTop : 0);
      $("#fvtt").css({ "top": (mouseY + 2) + "px", "left": (mouseX - 40) + "px" });
    },

    reloadAutoTip: function(validatorGroup) {
      if (validatorGroup == undefined) validatorGroup = "1";
      var initConfig = $.formValidator.getInitConfig(validatorGroup);
      $.each(initConfig.validObjects, function() {
        if (initConfig.mode == "AutoTip") {
          //获取层的ID、相对定位控件的ID和坐标
          var setting = this.settings[0];
          var relativeID = "#" + setting.relativeID;
          var offset = $(relativeID).offset();
          var y = offset.top;
          var x = $(relativeID).width() + offset.left;
          $("#" + setting.tipID).parent().show().css({ left: x + "px", top: y + "px" });
        }
      });
    },

    getStatusText: function(elem, obj) {
      return ($.isFunction(obj) ? obj($(elem).val()) : obj);
    },

    resetInputValue: function(real, initConfig, id) {
      var showTextObjects;
      if (id) {
        showTextObjects = $("#" + id);
      } else {
        showTextObjects = $(initConfig.showTextObjects);
      }
      showTextObjects.each(function(index, elem) {
        if (elem.isInputControl) {
          var showText = elem.settings[0].onShowText;
          if (real && showText == elem.value) {
            elem.value = "";
          };
          if (!real && showText != "" && elem.value == "") {
            elem.value = showText;
          };
        }
      });
    }
  };

//每个校验控件必须初始化的
  $.fn.formValidator = function(cs) {
    cs = cs || {};
    var setting = {};

    //获取该校验组的全局配置信息
    if (cs.validatorGroup == undefined) {
      cs.validatorGroup = "1";
    };

    //先合并整个配置(深度拷贝)
    $.extend(true, setting, formValidator_setting);

    var initConfig = $.formValidator.getInitConfig(cs.validatorGroup);

    //校验索引号，和总记录数
    initConfig.validCount += 1;

    //如果为精简模式，tipCss要重新设置初始值
    if (initConfig.mode == "SingleTip") {
      setting.tipCss = { left: 10, top: 1, width: 22, height: 22, display: "none" };
    };

    //弹出消息提示模式，自动修复错误
    if (initConfig.mode == "AlertTip") {
      setting.autoModify = true;
    };

    //先合并整个配置(深度拷贝)
    $.extend(true, setting, cs || {});

    return this.each(function(e) {
      //记录该控件的校验顺序号和校验组号
      this.validatorIndex = initConfig.validCount - 1;
      this.validatorGroup = cs.validatorGroup;
      var jqobj = $(this);
      //自动形成TIP
      var setting_temp = {};
      $.extend(true, setting_temp, setting);
      //判断是否有ID
      var id = jqobj.attr("id");
      if (!id) {
        id = Math.ceil(Math.random() * 50000000);
        jqobj.attr("id", id);
      }
      var tip = setting_temp.tipID ? setting_temp.tipID : id + "Tip";

      if (initConfig.mode == "AutoTip" || initConfig.mode == "FixTip") {
        var tipDiv = $("#" + tip);
        //获取层的ID、相对定位控件的ID和坐标
        if (initConfig.mode == "AutoTip" && tipDiv.length == 0) {
          tipDiv = $("<div style='position:absolute;' id='" + tip + "'></div>");
          var relativeID = setting_temp.relativeID ? setting_temp.relativeID : id;
          var offset = $("#" + relativeID).offset();
          setting_temp.tipCss.top = offset.top + setting_temp.tipCss.top;
          setting_temp.tipCss.left = $("#" + relativeID).width() + offset.left + setting_temp.tipCss.left;
          var formValidateTip = $("<div style='position:absolute;' id='" + tip + "'></div>").appendTo($("body"));
          formValidateTip.css(setting_temp.tipCss);
          setting.relativeID = relativeID;
        }
        tipDiv.css("margin", "0px").css("padding", "0px").css("background", "transparent");
      } else if (initConfig.mode == "SingleTip") {
        jqobj.showTooltips();
      }

      //每个控件都要保存这个配置信息、为了取数方便，冗余一份控件总体配置到控件上
      setting.tipID = tip;
      setting.pwdTipID = setting_temp.pwdTipID ? setting_temp.pwdTipID : setting.tipID;
      setting.fixTipID = setting_temp.fixTipID ? setting_temp.fixTipID : id + "FixTip";
      $.formValidator.appendValid(id, setting);

      //保存控件ID
      var validIndex = $.inArray(jqobj, initConfig.validObjects);
      if (validIndex == -1) {
        if (setting_temp.ajax) {
          var ajax = initConfig.ajaxObjects;
          initConfig.ajaxObjects = ajax + (ajax != "" ? ",#" : "#") + id;
        }
        initConfig.validObjects.push(this);
      } else {
        initConfig.validObjects[validIndex] = this;
      }

      //初始化显示信息
      if (initConfig.mode != "AlertTip") {
        $.formValidator.setTipState(this, "onShow", setting.onShow);
      }

      var srcTag = this.tagName.toLowerCase();
      var stype = this.type;
      var defaultval = setting.defaultValue;
      var isInputControl = stype == "password" || stype == "text" || stype == "textarea";
      this.isInputControl = isInputControl;
      //处理默认值
      if (defaultval) {
        jqobj.val(defaultval);
      }
      //固定提示内容
      var fixTip = $("#" + setting.fixTipID);
      var showFixText = setting.onShowFixText;
      if (fixTip.length == 1 && onMouseOutFixTextHtml != "" && onMouseOnFixTextHtml != "" && showFixText != "") {
        jqobj.hover(
          function() {
            fixTip.html(onMouseOnFixTextHtml.replace(/\$data\$/g, showFixText));
          },
          function() {
            fixTip.html(onMouseOutFixTextHtml.replace(/\$data\$/g, showFixText));
          }
        );
        fixTip.css("padding", "0px 0px 0px 0px").css("margin", "0px 0px 0px 0px").html(onMouseOutFixTextHtml.replace(/\$data\$/g, setting.onShowFixText));
      }
      //获取输入框内的提示内容
      var showText = setting.onShowText;
      if (srcTag == "input" || srcTag == "textarea") {
        if (isInputControl) {
          if (showText != "") {
            showObjs = initConfig.showTextObjects;
            initConfig.showTextObjects = showObjs + (showObjs != "" ? ",#" : "#") + id;
            jqobj.val(showText);
            jqobj.css("color", setting.onShowTextColor.mouseOutColor);
          }
        }
        //注册获得焦点的事件。改变提示对象的文字和样式，保存原值
        jqobj.focus(function() {
          if (isInputControl) {
            var val = jqobj.val();
            this.validValueOld = val;
            if (showText == val) {
              this.value = "";
              jqobj.css("color", setting.onShowTextColor.mouseOnColor);
            }
          };
          if (initConfig.mode != "AlertTip") {
            //保存原来的状态
            var tipjq = $("#" + tip);
            this.lastshowclass = tipjq.attr("class");
            this.lastshowmsg = tipjq.text();
            $.formValidator.setTipState(this, "onFocus", setting.onFocus);
          };
          if (this.validatorPasswordIndex > 0) {
            $("#" + setting.pwdTipID).show();
            jqobj.trigger("keyup");
          }
        });
        //按键时候触发校验
        jqobj.bind("keyup", function() {
          if (this.validatorPasswordIndex > 0) {
            try {
              var returnObj = $.formValidator.oneIsValid(id);
              var level = $.formValidator.passwordValid(this);
              if (level < 0) {
                level = 0;
              };
              if (!returnObj.isValid) {
                level = 0;
              };
              $("#" + setting.pwdTipID).show();
              $("#" + setting.pwdTipID).html(passwordStrengthStatusHtml[level]);
            } catch (e) {
              alert("密码强度校验失败,错误原因:变量passwordStrengthStatusHtml语法错误或者为设置)");
            }
          }
        });
        //注册失去焦点的事件。进行校验，改变提示对象的文字和样式；出错就提示处理
        jqobj.bind(setting.triggerEvent, function() {
          var settings = this.settings;
          //根据配置截掉左右的空格
          if (settings[0].leftTrim) {
            this.value = this.replace(/^\s*/g, "");
          }
          if (settings[0].rightTrim) {
            this.value = this.replace(/\s*$/g, "");
          }
          //恢复默认值
          if (isInputControl) {
            if (this.value == "" && showText != "") {
              this.value = showText;
            }
            if (this.value == showText) {
              jqobj.css("color", setting.onShowTextColor.mouseOutColor);
            }
          }
          //进行有效性校验
          var returnObj = $.formValidator.oneIsValid(id);
          if (returnObj == null) {
            return;
          }
          if (returnObj.ajax >= 0) {
            $.formValidator.showAjaxMessage(returnObj);
          } else {
            var showmsg = $.formValidator.showMessage(returnObj);
            if (!returnObj.isValid) {
              //自动修正错误
              var auto = setting.autoModify && isInputControl;
              if (auto) {
                $(this).val(this.validValueOld);
                if (initConfig.mode != "AlertTip") {
                  $.formValidator.setTipState(this, "onShow", $.formValidator.getStatusText(this, setting.onCorrect));
                };
              } else {
                if (initConfig.forceValid || setting.forceValid) {
                  alert(showmsg);
                  this.focus();
                }
              }
            }
          }
        });
      } else if (srcTag == "select") {
        jqobj.bind({
          //获得焦点
          focus: function() {
            if (initConfig.mode != "AlertTip") {
              $.formValidator.setTipState(this, "onFocus", setting.onFocus);
            };
          },
          //失去焦点
          blur: function() {
            if (this.validValueOld == undefined || this.validValueOld == jqobj.val()) {
              $(this).trigger("change");
            }
          },
          //选择项目后触发
          change: function() {
            var returnObj = $.formValidator.oneIsValid(id);
            if (returnObj == null) {
              return;
            }
            if (returnObj.ajax >= 0) {
              $.formValidator.showAjaxMessage(returnObj);
            } else {
              $.formValidator.showMessage(returnObj);
            }
          }
        });
      }
    });
  };

  $.fn.inputValidator = function(controlOptions) {
    var settings = {};
    $.extend(true, settings, inputValidator_setting, controlOptions || {});
    return this.each(function() {
      $.formValidator.appendValid(this.id, settings);
    });
  };

  $.fn.compareValidator = function(controlOptions) {
    var settings = {};
    $.extend(true, settings, compareValidator_setting, controlOptions || {});
    return this.each(function() {
      $.formValidator.appendValid(this.id, settings);
    });
  };

  $.fn.regexValidator = function(controlOptions) {
    var settings = {};
    $.extend(true, settings, regexValidator_setting, controlOptions || {});
    return this.each(function() {
      $.formValidator.appendValid(this.id, settings);
    });
  };

  $.fn.functionValidator = function(controlOptions) {
    var settings = {};
    $.extend(true, settings, functionValidator_setting, controlOptions || {});
    return this.each(function() {
      $.formValidator.appendValid(this.id, settings);
    });
  };

  $.fn.ajaxValidator = function(controlOptions) {
    var settings = {};
    $.extend(true, settings, ajaxValidator_setting, controlOptions || {});
    return this.each(function() {
      var initConfig = $.formValidator.getInitConfig(this.validatorGroup);
      var ajax = initConfig.ajaxObjects;
      if ((ajax + ",").indexOf("#" + this.id + ",") == -1) {
        initConfig.ajaxObjects = ajax + (ajax != "" ? ",#" : "#") + this.id;
      }
      this.validatorAjaxIndex = $.formValidator.appendValid(this.id, settings);
    });
  };

  $.fn.passwordValidator = function(controlOptions) {
    //默认配置
    var settings = {};
    $.extend(true, settings, passwordValidator_setting, controlOptions || {});
    return this.each(function() {
      this.validatorPasswordIndex = $.formValidator.appendValid(this.id, settings);
    });
  };

//指定控件显示通过或不通过样式
  $.fn.defaultPassed = function(onShow) {
    return this.each(function() {
      var settings = this.settings;
      settings[0].defaultPassed = true;
      this.onceValided = true;
      for (var i = 1; i < settings.length; i ++) {
        settings[i].isValid = true;
        if (!$.formValidator.getInitConfig(settings[0].validatorGroup).mode == "AlertTip") {
          var ls_style = onShow ? "onShow" : "onCorrect";
          $.formValidator.setTipState(this, ls_style, settings[0].onCorrect);
        }
      }
    });
  };

//指定控件不参加校验
  $.fn.unFormValidator = function(unbind) {
    return this.each(function() {
      if (this.settings) {
        this.settings[0].bind = !unbind;
        if (unbind) {
          $("#" + this.settings[0].tipID).hide();
        } else {
          $("#" + this.settings[0].tipID).show();
        }
      }
    });
  };

//显示漂浮显示层
  $.fn.showTooltips = function() {
    if ($("body [id=fvtt]").length == 0) {
      fvtt = $("<div id='fvtt' style='position:absolute;z-index:56002'></div>");
      $("body").append(fvtt);
      fvtt.before("<iframe index=0 src='about:blank' class='fv_iframe' scrolling='no' frameborder='0'></iframe>");

    }
    return this.each(function() {
      jqobj = $(this);
      s = $("<span class='top' id=fv_content style='display:block'></span>");
      b = $("<b class='bottom' style='display:block' />");
      this.tooltip = $("<span class='fv_tooltip' style='display:block'></span>").append(s).append(b).css({ "filter": "alpha(opacity:95)", "KHTMLOpacity": "0.95", "MozOpacity": "0.95", "opacity": "0.95" });
      //注册事件
      jqobj.bind({
        mouseover: function(e) {
          $("#fvtt").empty().append(this.tooltip).show();
          $("#fv_content").html(this.Tooltip);
          $.formValidator.localTooltip(e);
        },
        mouseout: function() {
          $("#fvtt").hide();
        },
        mousemove: function(e) {
          $.formValidator.localTooltip(e);
        }
      });
    });
  };
})(jQuery);

var initConfig_setting =
{
  theme: "Default",
  validatorGroup: "1", //分组号
  formID: "", //表单ID
  submitOnce: false, //页面是否提交一次，不会停留
  ajaxForm: null, //如果不为null，表示整个表单ajax提交
  mode: "FixTip", //显示模式
  errorFocus: true, //第一个错误的控件获得焦点
  wideWord: true, //一个汉字当做2个长
  forceValid: false, //控件输入正确之后，才允许失去焦
  debug: false, //调试模式点
  inIframe: false,
  onSuccess: function() { return true; }, //提交成功后的回调函数
  onError: $.noop, //提交失败的回调函数度
  status: "", //提交的状态：submited、sumbiting、sumbitingWithAjax
  ajaxPrompt: "当前有数据正在进行服务器端校验，请稍候", //控件失去焦点后，触发ajax校验，没有返回结果前的错误提示
  validCount: 0, //含ajaxValidator的控件个数
  ajaxCountSubmit: 0, //提交的时候触发的ajax验证个数
  ajaxCountValid: 0, //失去焦点时候触发的ajax验证个数
  validObjects: [], //参加校验的控件集合
  ajaxObjects: "", //传到服务器的控件列表
  showTextObjects: "",
  validateType: "initConfig"
};

var formValidator_setting =
{
  validatorGroup: "1",
  onShowText: "",
  onShowTextColor: { mouseOnColor: "#000000", mouseOutColor: "#999999" },
  onShowFixText: "",
  onShow: "请输入内容",
  onFocus: "请输入内容",
  onCorrect: "输入正确",
  onEmpty: "输入内容为空",
  empty: false,
  autoModify: false,
  defaultValue: null,
  bind: true,
  ajax: false,
  validateType: "formValidator",
  tipCss:
  {
    left: 10,
    top: -4,
    height: 20,
    width: 280
  },
  triggerEvent: "blur",
  forceValid: false,
  tipID: null,
  pwdTipID: null,
  fixTipID: null,
  relativeID: null,
  index: 0,
  leftTrim: false,
  rightTrim: false
};

var inputValidator_setting =
{
  isValid: false,
  type: "size",
  min: 0,
  max: 99999,
  onError: "输入错误",
  validateType: "inputValidator",
  empty: { leftEmpty: true, rightEmpty: true, leftEmptyError: null, rightEmptyError: null }
};

var compareValidator_setting =
{
  isValid: false,
  desID: "",
  operateor: "=",
  onError: "输入错误",
  validateType: "compareValidator"
};

var regexValidator_setting =
{
  isValid: false,
  regExp: "",
  param: "i",
  dataType: "string",
  compareType: "||",
  onError: "输入的格式不正确",
  validateType: "regexValidator"
};

var ajaxForm_setting =
{
  type: "GET",
  url: window.location.href,
  dataType: "html",
  timeout: 100000,
  data: null,
  async: true,
  cache: false,
  buttons: null,
  beforeSend: function() { return true; },
  success: function() { return true; },
  complete: $.noop,
  processData: true,
  error: $.noop
};

var ajaxValidator_setting =
{
  isValid: false,
  lastValid: "",
  oneceValid: false,
  randNumberName: "rand",
  onError: "服务器校验没有通过",
  onWait: "正在等待服务器返回数据",
  validateType: "ajaxValidator"
};
$.extend(true, ajaxValidator_setting, ajaxForm_setting);

var functionValidator_setting =
{
  isValid: true,
  fun: function() { this.isValid = true; },
  validateType: "functionValidator",
  onError: "输入错误"
};

var passwordValidator_setting = {
  isValid: true,
  compareID: "",
  validateType: "passwordValidator",
  onErrorContinueChar: "密码字符为连续字符不被允许",
  onErrorSameChar: "密码字符都相同不被允许",
  onErrorCompareSame: "密码于用户名相同不被允许"
};

var validatorGroup_setting = [];

var fv_scriptSrc = document.getElementsByTagName("script")[document.getElementsByTagName("script").length - 1].src;